ThoughtSpot Everywhere(埋め込み)のチュートリアルをCodeSandboxでやってみた
データアナリティクス事業本部、池田です。
ThoughtSpot Everywhere というものがリリースされましたので、
まずはチュートリアルをやってみました。
【 検索とAIを活用した分析で対話型データアプリを構築するローコードプラットフォーム、ThoughtSpot Everywhereが登場 】
ThoughtSpot Everywhereは、デベロッパーやプロダクトリーダーが対話型のデータアプリを構築し、検索とAIを活用した分析などのモダンアナリティクスクラウドで利用できるサービスをアプリ、製品、サービスに統合可能な初のローコード埋め込み分析プラットフォームです。
WebアプリにThoughtSpotを埋め込むことができるようですね。
ThoughtSpot Everywhereのリリースと同時に、デベロッパーがThoughtSpotのサービスをテスト・実験するためのデベロッパープレイグラウンドも発表しました。
デベロッパープレイグラウンドについても使用したので、後述します。
デモ動画はいくつかありましたが、個人的には↓が分かりやすかったです。
【 Build interactive data apps with search-driven analytics 】
チュートリアル
ThoughtSpot for Developers で公開されている Tutorials がThoughtSpot Everywhere(以下TSE)のチュートリアルのようなのでやってみました。
以下、本章ではチュートリアルの章立てに沿って、ポイントだけコメントしていきます。 (なお、チュートリアルの内容やコードは執筆時点のものなので、必要に応じて適宜読み替えて下さい。)
1. Overview
TSEの埋め込みはVisual Embed SDKというSDKを使ってJavaScript+HTMLで実装します。
このチュートリアルでは使いませんが、
JSについては各種フレームワークが使えるようで、↓Reactを使ったサンプルが公開されています。
【 ThoughtSpot EverywhereでReactアプリに対話型分析を埋め込む 】
2. Getting started
このページでは、ThoughtSpotやWebサーバーといった実行環境について説明されています。
今回私は…
- ThoughtSpot: サンプル公開されているデベロッパープレイグラウンド developers.thoughtspot.com/try
- 実行環境: CodeSandbox
の組み合わせで行いました。(動かすだけなら登録なども一切ありませんでした。)
ローカルでなく、CodeSandboxを選んだ理由は最後の節に書きます。
※
ThoughtSpotをトライアル版でやってみる場合は以前のブログをご覧下さい。
【 ThoughtSpot Cloudのトライアルを始めてSearch Answersを使ってみた 】
3. Using the Developer Portal
Developer Portal(ThoughtSpotの「DEVELOP」タブ)について説明されています。 なお、Developer Portalは執筆時点では、ThoughtSpot Cloudのみ(インストール版は未対応)とのことです。
デベロッパープレイグラウンド(Playground)もこの機能の一部のようです。 検索画面や作成したピンボードなどを、 疑似的に埋め込んで見栄えを確認したり、 実際に埋め込みに使用するコードを生成できます。
4. Implementation Steps
ここがメインの工程で、実装を行っています。
GitHub上のコード のうち、
tse_tutorial
フォルダだけ使うようです。
index.html
<div id='embed'> </div>
Visual Embed SDKでは特定のdivタグ(チュートリアルであれば embed
というidのdiv)に対して埋め込みを行ってくれるようです。
tse.js
const { init, Action, AppEmbed, AuthType, EmbedEvent, Page, PinboardEmbed, SearchEmbed, } = tsembed;
init
で初期化した後、
検索であれば SearchEmbed
、ピンボードやその一部であれば PinboardEmbed
、
アプリケーションであれば AppEmbed
といった部品でそれぞれ生成し、
.render()
して描画する流れのようです。
( ドキュメント )
CodeSandbox上での作業
CodeSandbox上では以下のように作業しました。
- サンドボックス作成時に、フォルダまで指定してGitHubからインポート
(↑Forkというのが気になったのですが、この時点ではGitHubにリポジトリが作成されるようなことはありませんでした。たぶん。)↓サンドボックスが作成され、左側にインポートしたファイル群、右側にプレビューが表示されます。
(↓ちなみに、この段階(GitHubのまま)のコードで画面操作していくと、実装がまだだと言われます。)
- チュートリアルの説明に沿って、
tse.js
ファイルを編集この時、デベロッパープレイグラウンド(Developer Portal)を使って、 設定するデータソースやピンボードのIDなどを取得していきます。
(↑画像は検索画面の埋め込み時に指定するデータソースのIDを取得しているところ。)実際の実装でも、プレイグラウンド上でIDを確認したり表示のオプションをいろいろ設定したりしながら、 アプリ開発していくのだろうなー、と想像しました。
チュートリアルのアプリケーションの埋め込みのところの説明によると…
Using the path attribute lets you go to any location. In particular, this can be good for embedding pinboards vs. the PinboardEmbed. When you use PinboardEmbed you get a limited number of options, for example, you can't make a copy. But if you give a path to the pinboard, you get all available options (that aren't disabled).
とのことで、同じピンボードでも、
PinboardEmbed
でピンボード埋め込むと、↓オプションが制限されますが…
AppEmbed
でピンボードのページを埋め込むと、↓選べるオプションなどが増えるようです。
(↑どうでも良いですが、 index.html
をいじって左上のロゴを弊社のものにしてみました。)
この辺は使い分けが必要そうですね。
今回のチュートリアルで実装した tse.js
コードが↓です。
クリックでコードを表示する/折りたたむ
(★のコメントしている部分が、GitHubからの変更箇所です。)
/* * This is the script to update for the ThoughtSpot Everywhere tutorial. */ import { ActionData, tabularDataToHTML } from "./dataclasses.js"; const { init, Action, AppEmbed, AuthType, EmbedEvent, Page, PinboardEmbed, SearchEmbed } = tsembed; const tsURL = "https://try-everywhere.thoughtspot.cloud"; // ★ // functions to show and hide div sections. const showDiv = (divId) => { const div = document.getElementById(divId); div.style.display = "flex"; }; const hideDiv = (divId) => { const div = document.getElementById(divId); div.style.display = "none"; }; const clearEmbed = () => { const div = document.getElementById("embed"); div.innerHTML = ""; }; const closeModal = () => { const showDataElement = document.getElementById("show-data"); showDataElement.style.display = "none"; // hide the box. }; const showData = (payload) => { // TODO - add code to handle the custom action callback. }; // Create and manage the login screen. const onLogin = () => { // The following can be used if you want to use AuthType.Basic //const username = document.getElementById('username').value; //const password = document.getElementById('password').value; // ★~ init({ thoughtSpotHost: tsURL, authType: AuthType.None }); // ~★ hideDiv("login"); showDiv("landing-page"); }; const showMainApp = () => { // Clears out the page and shows the main app. // This can be called from any page to make sure the state is correct. clearEmbed(); // just to be sure. hideDiv("landing-page"); showDiv("main-app"); }; // Functions to embed the content based on user selection. const onSearch = () => { showMainApp(); // ★~ const embed = new SearchEmbed("#embed", { frameParams: {}, dataSources: ["cd252e5c-b552-49a8-821d-3eadaa049cca"], disabledActions: [Action.SpotIQAnalyze], disabledActionReason: "Enterprise feature.", hiddenActions: [Action.Download, Action.Share, Action.DownloadAsCsv] }); embed.render(); // ~★ }; const onVisualization = () => { showMainApp(); // ★~ const embed = new PinboardEmbed("#embed", { frameParams: {}, pinboardId: "66f5bf76-b0a9-40b4-94b3-a93a7180c1da", vizId: "92e2a902-ec53-422a-83e1-9b125cc0cc5e", disabledActions: [Action.Download], disabledActionReason: "Enterprise feature.", hiddenActions: [Action.SpotIQAnalyze] }); embed.render(); // ~★ }; const onPinboard = () => { showMainApp(); // ★~ const embed = new PinboardEmbed("#embed", { frameParams: {}, pinboardId: "543619d6-0015-4667-b257-eff547d13a12", disabledActions: [Action.DownloadAsPdf], disabledActionReason: "Enterprise feature.", hiddenActions: [Action.PinboardInfo] }); embed.render(); // ~★ }; // Embed the full application. const onFull = () => { showMainApp(); // ★~ const embed = new AppEmbed("#embed", { frameParams: {}, // pageId: Page.Home // loads the Home tab. Others can be loaded. See Page enum. path: "pinboard/543619d6-0015-4667-b257-eff547d13a12" // loads the Home tab. Others can be loaded. See Page enum. }); embed.render(); // ~★ }; export { onLogin, onFull, onSearch, onPinboard, onVisualization }; // Show the URL to connect to. document.getElementById("ts-url").innerText = "ThoughtSpot Server: " + tsURL; // Hook up the events to the buttons and links. document.getElementById("login-button").addEventListener("click", onLogin); document.getElementById("close-modal").addEventListener("click", closeModal); // Events for buttons document.getElementById("search-button").addEventListener("click", onSearch); document .getElementById("pinboard-button") .addEventListener("click", onPinboard); document .getElementById("viz-button") .addEventListener("click", onVisualization); document.getElementById("full-app-button").addEventListener("click", onFull); // Events for nav bar document.getElementById("search-link").addEventListener("click", onSearch); document.getElementById("pinboard-link").addEventListener("click", onPinboard); document .getElementById("visualization-link") .addEventListener("click", onVisualization); document .getElementById("full-application-link") .addEventListener("click", onFull);
↓CodeSandboxだとこんな感じ。
【 codesandbox.io 】 ※アプリ動かせます
5. Conclusion
細かいことは ドキュメント を読めとのこと。
6. Appendix A: Development Environment
ここではChromeのデバッグについて教えてくれています。親切!
7. Appendix B: Security Settings
ここでは、セキュリティ(CSP・CORS)設定について説明があります。
Developer Portal(「DEVELOP」タブ)で設定ができるみたいですね。
今回、CodeSandboxでやってみた理由ですが、
使用した公開されている環境の developers.thoughtspot.com/try
が CSP
の制限でlocalhostで使えなかったからです。
(ブログにCodeSandboxを埋め込むこともできませんでした…)
ローカル環境で試したい方はThoughtSpot Cloudのトライアルで試してみて下さい。
おわりに
TSEでThoughtSpotの活用の幅が広がりそうですね。 デベロッパープレイグラウンドも重要な機能そうです。
CodeSandboxも便利でした。 私はフレームワークをあまり使ったことが無いのですが、よく使う方はもっと嬉しいのですかね。
関連情報/参考にさせていただいたページ
- ThoughtSpot Everywhere
- CodeSandbox
- CSP: frame-src